#ifndef XXLOGGER_H
#define XXLOGGER_H

#include <QObject>
#include <QVariant>
#include <QSharedPointer>

/* 废弃，请不要使用 */
#define xxLog(_format_,...) \
    {\
        QString _msg_ = QString("[%1] [%2] %3\n").arg(__FUNCTION__).arg(__LINE__).arg(QString::asprintf(_format_,##__VA_ARGS__)); \
        XXlogger::instance().message(_msg_); \
    }
/* 废弃，请不要使用 */
#define xxLogStr(_string_)  \
    {\
        QString _msg_ = QString("[%1] [%2] %3\n").arg(__FUNCTION__).arg(__LINE__).arg(_string_); \
        XXlogger::instance().message(_msg_); \
    }
/* 废弃，请不要使用 */
#define xxLogStrF(_stringF_)  \
    {\
        QString _msg_ = QString("[%1] [%2] %3\n").arg(__FUNCTION__).arg(__LINE__).arg(QString _stringF_); \
        XXlogger::instance().message(_msg_); \
    }

// [-] 格式化输出。
#define xxl(_type_,_format_,...) \
    {\
        QString _msg_ = QString("[%1] [%2] [%3] %4\n").arg(_type_).arg(__FUNCTION__).arg(__LINE__).arg(QString::asprintf(_format_,##__VA_ARGS__)); \
        XXlogger::instance().message(_msg_); \
    }
#define xxls(_type_,_string_)  \
    {\
        QString _msg_ = QString("[%1] [%2] [%3] %4\n").arg(_type_).arg(__FUNCTION__).arg(__LINE__).arg(_string_); \
        XXlogger::instance().message(_msg_); \
    }
#define xxlsf(_type_,_stringF_)  \
    {\
        QString _msg_ = QString("[%1] [%2] [%3] %4\n").arg(_type_).arg(__FUNCTION__).arg(__LINE__).arg(QString _stringF_); \
        XXlogger::instance().message(_msg_); \
    }
// [!] 格式化输出。


// [-] 异常信息输出。
#define xxErr(_format_,...) \
    {\
        xxl("ERROR",_format_,##__VA_ARGS__)\
    }
#define xxErrStr(_string_)  \
    {\
        xxls("ERROR",_string_)\
    }
#define xxErrStrF(_stringF_)  \
    {\
        xxlsf("ERROR",_stringF_); \
    }
// [!] 异常信息输出。


// [-] 一般信息输出。
#define xxInfo(_format_,...) \
    {\
        xxl("INFO",_format_,##__VA_ARGS__)\
    }
#define xxInfoStr(_string_)  \
    {\
        xxls("INFO",_string_)\
    }
#define xxInfoStrF(_stringF_)  \
    {\
        xxlsf("INFO",_stringF_); \
    }
// [!] 一般信息输出。


// [-] 警告信息输出。
#define xxWarning(_format_,...) \
    {\
        xxl("WARNING",_format_,##__VA_ARGS__)\
    }
#define xxWarningStr(_string_)  \
    {\
        xxls("WARNING",_string_)\
    }
#define xxWarningStrF(_stringF_)  \
    {\
        xxlsf("WARNING",_stringF_); \
    }
// [!] 警告信息输出。


/* 内部使用，请不要使用 */
#define xxLogWithout(fifo,format,...) \
    {\
        QString msg = QString("[%1] [%2] %3\n").arg(__FUNCTION__).arg(__LINE__).arg(QString::asprintf(format,##__VA_ARGS__)); \
        XXlogger::instance().message(fifo,msg); \
    }
/* 内部使用，请不要使用 */
#define xxLogStrWithout(fifo,string)  \
    {\
        QString msg = QString("[%1] [%2] %3\n").arg(__FUNCTION__).arg(__LINE__).arg(string); \
        XXlogger::instance().message(fifo,msg); \
    }

class XXfifoBase : public QObject{
    Q_OBJECT
public:
    XXfifoBase(QObject *parent = nullptr) : QObject(parent){}
    virtual ~XXfifoBase() {}

    /**
     * @brief reset 对通道进行参数配置。
     * @param param
     */
    virtual void reset(const QVariantMap &param) = 0;

    /**
     * @brief push 对通道推送信息。
     * @param data
     */
    virtual void push(const QByteArray &data) = 0;

    /**
     * @brief isEnabled 标识通道是否使能。
     * @return
     */
    virtual bool isEnabled() const { return _enable; }

    /**
     * @brief setEnable 设置通道是否使能。
     * @param enable
     */
    virtual void setEnable(bool enable){ _enable = enable; }

    /**
     * @brief name 获取通道名称标识。
     * @return
     */
    virtual QString name() const { return _name; }

    /**
     * @brief setName 设置通道名称标识。
     * @param name
     */
    virtual void setName(const QString &name) { _name = name; }

protected:
    /* 使能标识 */
    bool _enable;

    /* 通道名称标识 */
    QString _name;
};

/**
 * @brief The XXlogger class
 * 默认配置了以下fifo
 *  - qDebug，name=“qDebugFifo”
 *  - file，name=“fileFifo”，默认路径为/「home」/「App」/xxlogger，文件格式为「yyyy-MM-dd」
 */
class XXlogger : public QObject{
    Q_OBJECT
public:
    XXlogger();
    virtual ~XXlogger() {}

    /**
     * @brief message 信息输出
     * @param msg 需要输出的信息
     * @param sample 设置为true，则不会在msg前增加时间信息。
     */
    void message(const QString &msg, bool sample = false);

    /**
     * @brief message 信息输出，并可以过滤指定的fifo
     * @param msg 需要输出的信息
     */
    void message(XXfifoBase *without, const QString &msg, bool sample = false);

    /**
     * @brief configFifo 配置目标fifo（需要继承XXfifoBase），并移交释放权到XXlogger中，name相当是对应fifo的控制key；
     * @param name fifo的别名，不要与默认别名重复，默认fifo别名有：kdefaultQDebugFifoName和kDefaultFileFifoName
     * @param fifo XXfifoBase的派生类
     */
    void configFifo(const QString &name, XXfifoBase *fifo);

    /**
     * @brief setFifoEnable 设置fifo的输出使能
     * @param name fifo的别名，默认fifo别名有：kdefaultQDebugFifoName和kDefaultFileFifoName
     * @param enable 是否使能
     */
    void setFifoEnable(const QString &name, bool enable);

    /**
     * @brief resetFifo 重置fifo，对应的参数需要与fifo派生类协定
     * @param name fifo的别名，默认fifo别名有：kdefaultQDebugFifoName和kDefaultFileFifoName
     * @param param fifo的参数
     */
    void resetFifo(const QString &name, const QVariantMap &param);

    /**
     * @brief instance 单例模式
     */
    static XXlogger& instance();

public: // 一些公开常量
    static const char * const kDefaultQDebugFifoName;
    static const char * const kDefaultFileFifoName;

private:
    void initDefaultFifo();
    void output(const QString &msg, XXfifoBase *without = nullptr, bool simple = false);

private:
    bool _qDebugFifoEnable;  // 由于qDebug使用的qt自带的，并没有进行派生封装，所以这里需要有一个变量描述其是否使能，默认是true；
    QMap<QString,QSharedPointer<XXfifoBase>> _nameToFifo;
    static XXlogger *_instance;
};

#endif // XXLOGGER_H
